#!/usr/bin/env ruby

## The MIT License (MIT)
##
## Copyright (c) 2018 SavinMax. All rights reserved.
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in
## all copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
## THE SOFTWARE.

require "yaml"
require "./tools/utils"

protos = Utils.load_protos
defines = protos[:defines]
game_msgs = protos[:game_msgs]
room_msgs = protos[:room_msgs]
rpc_msgs = protos[:rpc_msgs]

COMMON_TYPE = ['bool', 'byte', 'string', 
               'uint16', 'uint24', 'uint32', 'uint64', 
               'int16', 'int24', 'int32', 'int64',
               'float32', 'float64']

PROTOCOL_TYPE = []
defines.each do |proto|
  PROTOCOL_TYPE << proto['name']
end

header = %Q{\
/*
 * Generated by tools/gen_protocol
 */
}

#
# Generate protobuf files
#
package = "pt"
proto_dir = "../src/goslib/gen/api/#{package}"
`mkdir -p #{proto_dir}`
target = "#{proto_dir}/protocol.proto"

File.open(target, "w") do |io|
  io.write "//Generated by tools/gen_protocol_pb\n"
  io.write %Q(syntax = "proto3";\n)
  io.write "package pt;\n"
  defines.each do |proto|
    key = proto['name']
    field_defines = proto['struct']
    fields = []
    idx = 0
    field_defines.each do |field, type|
      type == "float32" and type = "float"
      idx += 1
      if type.index("array-") == 0
        sub_type = type.split('-')[1]
        if PROTOCOL_TYPE.include?(sub_type)
          fields << "repeated #{sub_type} #{field} = #{idx};"
        else
          fields << "repeated #{sub_type} #{field} = #{idx};"
        end
      else
        fields << "#{type} #{field} = #{idx};"
      end
    end
    io.write %Q{
message #{key} {
    #{fields.join("\n    ")}
}
    }
  end
end
`cd #{proto_dir} && protoc --go_out=. protocol.proto`

#
# Generate api map
#
target = "../src/goslib/gen/api/pt/api_map.go"

File.open(target, "w") do |io|
  consts = []

  pt_types = []
  id_to_type = []

  name_to_id = []
  id_to_name = []

  defines = {
    GS: game_msgs,
    ROOM: room_msgs,
    RPC: rpc_msgs
  }
  defines.keys.each_with_index do |type, idx|
    type_name = "PT_TYPE_#{type}"
    pt_types << %Q{#{type_name} = #{idx + 1}}

    defines[type].each do |proto|
      consts << %Q{PT_#{proto['name']} = "#{proto['name']}"}
      if proto['id']
        name_to_id << %Q{"#{proto['name']}": uint16(#{proto['id']})}
        id_to_name << %Q{uint16(#{proto['id']}): "#{proto['name']}"}
        id_to_type << %Q{uint16(#{proto['id']}): #{type_name}}
      end
    end
  end

  io.write %Q{\
#{header}
package pt

var NameToId = map[string]uint16{
    #{name_to_id.join(",\n    ")},
}

var IdToName = map[uint16]string{
    #{id_to_name.join(",\n    ")},
}

var IdToType = map[uint16]int{
    #{id_to_type.join(",\n    ")},
}

const(
    #{consts.join("\n    ")}
)

const(
    #{pt_types.join("\n    ")}
)
}
end
`gofmt -w #{target}`

`ruby tools/gen_protocol_pb`
`ruby tools/gen_protocol_raw`
`ruby tools/gen_protocol_json`
